package com.chixing.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chixing.entity.Movie;
import com.chixing.entity.MovieDetail;
import com.chixing.entity.OrderBase;
import com.chixing.entity.vo.MovieVO;
import com.chixing.mapper.MovieDetailMapper;
import com.chixing.mapper.MovieMapper;
import com.chixing.mapper.OrderBaseMapper;
import com.chixing.service.IMovieService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chixing.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liwenjing
 * @since 2025-10-07
 */
@Service
public class MovieServiceImpl  extends ServiceImpl<MovieMapper, Movie> implements IMovieService {


    @Autowired
    private MovieMapper movieMapper;
    @Autowired
    private MovieDetailMapper movieDetailMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Override
    public Result getHotMoviesByStatus(Integer status) {
        // 验证状态参数
        if (status == null || (status != 1 && status != 2)) {
            return Result.getFail("状态参数错误：1=热映中，2=即将上映");
        }

        String redisKey = getRedisKeyByStatus(status);
        List<MovieVO> movieList = null;

        if (!redisTemplate.hasKey(redisKey)) {
            // Redis中没有数据，从MySQL查询
            QueryWrapper<Movie> wrapper = new QueryWrapper<>();
            wrapper.eq("statues", status);

            // 根据状态设置不同的排序规则
            if (status == 1) {
                wrapper.orderByDesc("box_office"); // 热映电影按票房排序
            } else {
                wrapper.orderByDesc("create_time"); // 即将上映电影按创建时间排序
            }

            wrapper.last("LIMIT 10"); // 限制10条

            List<Movie> movies = movieMapper.selectList(wrapper);

            // 转换为VO列表
            movieList = convertToMovieVOList(movies);

            // 缓存到Redis
            if (!movieList.isEmpty()) {
                redisTemplate.opsForList().rightPushAll(redisKey, movieList.toArray());
                // 设置过期时间（例如1小时）
                // redisTemplate.expire(redisKey, 1, TimeUnit.HOURS);
            }
        } else {
            // 从Redis获取数据
            movieList = redisTemplate.opsForList().range(redisKey, 0, -1)
                    .stream()
                    .map(obj -> (MovieVO) obj)
                    .collect(Collectors.toList());
        }

        return Result.getSuccess(movieList);
    }

    @Override
    public Result getMoviesByStatusAndPage(Integer status, Integer pageNum) {
        // 验证状态参数
        if (status == null || (status != 1 && status != 2)) {
            return Result.getFail("状态参数错误：1=热映中，2=即将上映");
        }

        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }

        Page<Movie> page = new Page<>(pageNum, 9); // 每页10部电影
        QueryWrapper<Movie> wrapper = new QueryWrapper<>();
        wrapper.eq("statues", status);

        // 根据状态设置不同的排序规则
        if (status == 1) {
            wrapper.orderByDesc("box_office"); // 热映电影按票房排序
        } else {
            wrapper.orderByDesc("create_time"); // 即将上映电影按创建时间排序
        }

        page = movieMapper.selectPage(page, wrapper);

        // 转换为VO列表
        List<MovieVO> movieVOList = convertToMovieVOList(page.getRecords());

        // 创建新的分页对象返回VO
        Page<MovieVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(movieVOList);

        return Result.getSuccess(voPage);
    }

    @Override
    public Result getMovieDetailById(Integer movieId) {
        String key = "movie_detail_" + movieId;

        if (redisTemplate.hasKey(key)) {
            // Redis中有该电影详情，直接返回
            System.out.println("Redis中有该电影详情，直接返回");
            MovieVO movieVO = (MovieVO) redisTemplate.opsForValue().get(key);
            return Result.getSuccess(movieVO);
        } else {
            // Redis中没有，从MySQL查询
            System.out.println("Redis中没有该电影详情，执行MySQL查询");

            // 查询电影基本信息
            Movie movie = movieMapper.selectById(movieId);
            if (movie == null) {
                return Result.getFail("电影不存在");
            }

            // 查询电影详情信息
            QueryWrapper<MovieDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("movie_id", movieId);
            MovieDetail movieDetail = movieDetailMapper.selectOne(wrapper);

            // 封装VO对象
            MovieVO movieVO = convertToMovieVO(movie, movieDetail);

            // 缓存到Redis
            System.out.println("电影详情缓存到Redis中");
            redisTemplate.opsForValue().set(key, movieVO);

            return Result.getSuccess(movieVO);
        }
    }

    @Override
    public Long getMovieCountByStatus(Integer status) {
        QueryWrapper<Movie> wrapper = new QueryWrapper<>();
        wrapper.eq("statues", status);
        return movieMapper.selectCount(wrapper);
    }




    /**
     * 根据状态获取对应的Redis key
     */
    private String getRedisKeyByStatus(Integer status) {
        if (status == 1) {
            return "hotScreeningMovies";
        } else if (status == 2) {
            return "upcomingMovies";
        }
        return "movies_status_" + status;
    }

    /**
     * 将Movie列表转换为MovieVO列表
     */
    private List<MovieVO> convertToMovieVOList(List<Movie> movies) {
        return movies.stream().map(movie -> {
            // 查询对应的电影详情
            QueryWrapper<MovieDetail> detailWrapper = new QueryWrapper<>();
            detailWrapper.eq("movie_id", movie.getMovieId());
            MovieDetail movieDetail = movieDetailMapper.selectOne(detailWrapper);

            return convertToMovieVO(movie, movieDetail);
        }).collect(Collectors.toList());
    }

    /**
     * 将Movie和MovieDetail转换为MovieVO
     */
    private MovieVO convertToMovieVO(Movie movie, MovieDetail movieDetail) {
        MovieVO movieVO = new MovieVO(
                movie.getMovieId(),
                movie.getMovieName(),
                movie.getMovieImage(),
                movie.getMovieScore(),
                movie.getBoxOffice(),
                movie.getStatues(),
                movieDetail != null ? movieDetail.getMovieType() : null,
                movieDetail != null ? movieDetail.getReleaseTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null,

                movieDetail != null ? movieDetail.getDurationMinutes() : null
        );

        // 设置其他详情字段
        if (movieDetail != null) {
            movieVO.setMovieTrailer(movieDetail.getMovieTrailer());
            movieVO.setMovieIntro(movieDetail.getMovieIntro());
            movieVO.setReleaseLocation(movieDetail.getReleaseLocation());
            movieVO.setDuration(movieDetail.getDuration());
            movieVO.setDirector(movieDetail.getDirector());
            movieVO.setActors(movieDetail.getActors());
            movieVO.setImages(movieDetail.getImages());
        }

        return movieVO;
    }

    @Override
    public Result recommendByUserOrderType(Integer userId, Integer howMany) {
        // 1. 获取用户已下单的电影类型
        List<String> userOrderedTypes = movieMapper.selectOrderedMovieTypes(userId);
        if (userOrderedTypes == null || userOrderedTypes.isEmpty()) {
            return Result.getFail("用户暂无观影记录，无法推荐");
        }

        // 2. 收集推荐结果（去重）
        Set<Movie> recommendMovies = new HashSet<>();
        Set<Integer> excludeIds = new HashSet<>();

        // 3. 按类型推荐电影
        for (String type : userOrderedTypes) {
            // 每次推荐时排除已添加的电影ID
            List<Movie> typeMovies = movieMapper.selectByTypeAndExcludeIds(
                    type,
                    new ArrayList<>(excludeIds),
                    howMany / userOrderedTypes.size() + 1
            );

            // 添加到结果集并记录已推荐ID
            for (Movie movie : typeMovies) {
                if (recommendMovies.size() >= howMany) {
                    break;
                }
                recommendMovies.add(movie);
                excludeIds.add(movie.getMovieId());
            }

            if (recommendMovies.size() >= howMany) {
                break;
            }
        }

        return Result.getSuccess(new ArrayList<>(recommendMovies));
    }
}
